package cn.stylefeng.guns.modular.agv.service.impl;

import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.core.util.DateUtil;
import cn.stylefeng.guns.modular.agv.entity.AgvStorageTask;
import cn.stylefeng.guns.modular.agv.entity.HikAgvRoadWay;
import cn.stylefeng.guns.modular.agv.entity.HikAgvTask;
import cn.stylefeng.guns.modular.agv.mapper.HikAgvRoadWayMapper;
import cn.stylefeng.guns.modular.agv.mapper.HikAgvTaskMapper;
import cn.stylefeng.guns.modular.agv.model.params.HiKAgvCallbackParm;
import cn.stylefeng.guns.modular.agv.model.params.HikAgvRoadWayParam;
import cn.stylefeng.guns.modular.agv.model.params.HikAgvTaskParam;
import cn.stylefeng.guns.modular.agv.model.params.XlbClientParamVo;
import cn.stylefeng.guns.modular.agv.model.result.HikAgvRoadWayResult;
import cn.stylefeng.guns.modular.agv.model.result.HikAgvTaskResult;
import cn.stylefeng.guns.modular.agv.model.result.XlbClientRS;
import cn.stylefeng.guns.modular.agv.service.AgvStorageTaskService;
import  cn.stylefeng.guns.modular.agv.service.HikAgvTaskService;
import cn.stylefeng.guns.modular.agv.util.HikApiUtils;
import cn.stylefeng.guns.modular.agv.util.HikRsVo;
import cn.stylefeng.guns.modular.basic.model.params.BasicXlbOauth2tokenParam;
import cn.stylefeng.guns.modular.basic.model.result.BasicXlbOauth2tokenResult;
import cn.stylefeng.guns.modular.basic.service.BasicXlbOauth2tokenService;
import cn.stylefeng.guns.modular.hx.storage.entity.HxStorageOut;
import cn.stylefeng.guns.modular.hx.storage.service.HxStorageOutService;
import cn.stylefeng.guns.modular.order.mapper.OrderOutpreparePlatooncarMapper;
import cn.stylefeng.guns.modular.transport.utils.XlbApiUtils;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 海康AGV任务单 服务实现类
 * </p>
 *
 * @author zhangzh
 * @since 2024-06-06
 */
@Service
public class HikAgvTaskServiceImpl extends ServiceImpl<HikAgvTaskMapper, HikAgvTask> implements HikAgvTaskService {


    @Autowired
    private HikAgvRoadWayMapper hikAgvRoadWayMapper;

    @Autowired
    private OrderOutpreparePlatooncarMapper orderOutpreparePlatooncarMapper;

    @Autowired
    private BasicXlbOauth2tokenService basicXlbOauth2tokenService;

    @Autowired
    private AgvStorageTaskService agvStorageTaskService;

    @Autowired
    private HxStorageOutService hxStorageOutService;


    @Value("${hik.baseUrl}")
    private String tuskBaseUrl;

    @Value("${hxl.api.url}")
    private String hxlApiUrl;

    @Override
    public void add(HikAgvTaskParam param){
        HikAgvTask entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public ResponseData addTask(HikAgvTaskParam param) {

        // 查询当前终点 是否有同起点且未离开的任务
        HikAgvTaskParam q = new HikAgvTaskParam();
        q.setStat("01");
        q.setSrcPositionCode(param.getSrcPositionCode());
        List<HikAgvTaskResult> taskList = this.baseMapper.get01TaskList(q);
        if(taskList!=null && taskList.size() > 0){
            return ResponseData.error("起点【"+param.getSrcPositionCode()+"】存在未执行的任务，无法再次创建！！！");
        }
        //巷道号处理
        HikAgvRoadWay hikAgvRoadWay = new HikAgvRoadWay();
        hikAgvRoadWay.setRoadWayCode(param.getTarPositionCode());

        String roadWayCode = StringUtils.leftPad(param.getTarPositionCode(),3,"0");
        // 查询巷道信息 获取当前巷道对应的排序
        HikAgvRoadWayParam paramCondition = new HikAgvRoadWayParam();
        paramCondition.setRoadWayCode(param.getTarPositionCode());
        HikAgvRoadWayResult detail = hikAgvRoadWayMapper.getDetail(paramCondition);
        if(detail == null){
            return ResponseData.error("巷道未维护，清联系管理员！！！");
        }
        // 若存在直接使用，若不存在，则查找巷道号与门店对应
        if(ToolUtil.isNotEmpty(detail.getPlateNumber())){
            //获取到序号
            param.setCarReq(detail.getTrainSeq()+"");
            param.setTaskReq(detail.getTrainRoadWaySeq()+"");

            param.setClientId(detail.getClientId());
            param.setPlateNumber(detail.getPlateNumber());
        }else{
            //获取根据巷道号获取对应门店
            String xlbClientId = null;
            String xlbClientName = null;
//            String xlbClientId = this.baseMapper.getXlbClientId(roadWayCode + "通道");
            BasicXlbOauth2tokenParam oauth2tokenParam = new BasicXlbOauth2tokenParam();
            oauth2tokenParam.setGsnumber("66666");

            BasicXlbOauth2tokenResult oauth2tokenResult = basicXlbOauth2tokenService.findBySpec(oauth2tokenParam);
;            XlbClientParamVo apiParam = new XlbClientParamVo();
            apiParam.getChannelNames().add(roadWayCode + "通道");
            try{
                XlbClientRS clientInfo = XlbApiUtils.getClientInfo(this.hxlApiUrl, apiParam, oauth2tokenResult.getOauth2TokenXlb());
                if(clientInfo != null && clientInfo.getCode() == 0 && clientInfo.getData() != null && clientInfo.getData().size() > 0){
                    xlbClientId = clientInfo.getData().get(0).getClient_id();
                    xlbClientName = clientInfo.getData().get(0).getClient_name();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

            if(ToolUtil.isNotEmpty(xlbClientId)){
                param.setClientId(xlbClientId);
                hikAgvRoadWay.setClientId(xlbClientId);
                hikAgvRoadWay.setClientName(xlbClientName);
                //根据门店获取对应的司机
                String carnumber = orderOutpreparePlatooncarMapper.getCarnumber(xlbClientId, DateUtil.getDate());
                Integer maxTrainSeq = this.hikAgvRoadWayMapper.getMaxTrainSeq();
                if(ToolUtil.isNotEmpty(carnumber)){
                    param.setPlateNumber(carnumber);
                    hikAgvRoadWay.setPlateNumber(carnumber);
                    //根据司机和巷道号，获取排序信息
                    HikAgvRoadWayResult agvRoadWay = this.hikAgvRoadWayMapper.getTrainSeqByPlatNum(carnumber);
                    if(agvRoadWay == null){
                        param.setCarReq(String.valueOf(maxTrainSeq+1));
                        param.setTaskReq("1");
                    }else{
                        param.setCarReq(String.valueOf(agvRoadWay.getTrainSeq()));
                        param.setTaskReq(String.valueOf(agvRoadWay.getTrainRoadWaySeq() + 1));
                    }
                    //更新序号
                    hikAgvRoadWay.setTrainSeq(Integer.valueOf(param.getCarReq()));
                    hikAgvRoadWay.setTrainRoadWaySeq(Integer.valueOf(param.getTaskReq()));
                }else{
                    param.setCarReq(String.valueOf(maxTrainSeq+1));
                    param.setTaskReq("2");
                }
            }else{
                param.setCarReq("0");
                param.setTaskReq("2");
            }
        }
        //调用API接口
        HikRsVo hikRsVo = HikApiUtils.genAgvSchedulingTask(tuskBaseUrl, param);
        if (hikRsVo == null) {
            return ResponseData.error("接口调用错误");
        } else if (!"0".equals(hikRsVo.getCode() )) {
            return ResponseData.error(hikRsVo.getMessage());
        } else {
            //查询当前通道剩余托数
            Integer fullNum = hikAgvRoadWayMapper.getFullNum(param.getTarPositionCode());
            if(fullNum != null && fullNum < 1){
                param.setOverFlag("red");
            }
            param.setTaskNo(hikRsVo.getData());
            HikAgvTask entity = getEntity(param);
            this.save(entity);

            //更新巷道信息
            if(ToolUtil.isNotEmpty(hikAgvRoadWay.getPlateNumber())){
                hikAgvRoadWayMapper.updateById(hikAgvRoadWay);
            }

        }
        return ResponseData.success();
    }
    //长春下达agv任务
    @Override
    public ResponseData addTaskcc(HikAgvTaskParam param) {

        HikRsVo hikRsVo = HikApiUtils.genAgvSchedulingTask("http://192.168.10.90:8181/rcms/services/rest/hikRpcService", param);
        if (hikRsVo == null) {
            return ResponseData.error("接口调用错误");
        } else if (!"0".equals(hikRsVo.getCode() )) {
            return ResponseData.error(hikRsVo.getMessage());
        }
        return ResponseData.success();
    }
    @Override
    public void delete(HikAgvTaskParam param){
        this.removeById(getKey(param));
    }

    @Override
    public void update(HikAgvTaskParam param){
        HikAgvTask oldEntity = getOldEntity(param);
        HikAgvTask newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public HikAgvTaskResult findBySpec(HikAgvTaskParam param){
        return null;
    }

    @Override
    public List<HikAgvTaskResult> findListBySpec(HikAgvTaskParam param){
        return this.baseMapper.customList(param);
    }

    @Override
    public LayuiPageInfo findPageBySpec(HikAgvTaskParam param,String condition){
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList(pageContext, param,condition);
        return LayuiPageFactory.createPageInfo(page);
    }

    @Override
    public ResponseData setPriority(HikAgvTaskParam param) {
        HikRsVo hikRsVo = HikApiUtils.setTaskPriority(tuskBaseUrl, param);
        if (hikRsVo == null) {
            return ResponseData.error("接口调用错误");
        } else if (!"0".equals(hikRsVo.getCode() )) {
            return ResponseData.error(hikRsVo.getMessage());
        }
        HikAgvTaskParam save = new HikAgvTaskParam();
        save.setId(param.getId());
        save.setPriority(param.getPriority());
        HikAgvTask oldEntity = getOldEntity(save);
        HikAgvTask newEntity = getEntity(save);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
        return ResponseData.success();


    }

    @Override
    public ResponseData clear(String roadWayCode) {
        HikRsVo hikRsVo = HikApiUtils.clearRoadWay(tuskBaseUrl, roadWayCode);
        if (hikRsVo == null) {
            return ResponseData.error("接口调用错误");
        } else if (!"0".equals(hikRsVo.getCode() )) {
            return ResponseData.error(hikRsVo.getMessage());
        }
        HikAgvRoadWay hikAgvRoadWay = new HikAgvRoadWay();
        hikAgvRoadWay.setRoadWayCode(roadWayCode);
        hikAgvRoadWay.setSeq("0");
        hikAgvRoadWay.setTrainSeq(0);
        hikAgvRoadWay.setTrainRoadWaySeq(0);
        hikAgvRoadWay.setPlateNumber("");
        hikAgvRoadWay.setClientId("");
        hikAgvRoadWay.setClientName("");
        hikAgvRoadWayMapper.updateById(hikAgvRoadWay);
        return ResponseData.success();
    }

    @Override
    public ResponseData clear2(String roadWayCode) {
        HikRsVo hikRsVo = HikApiUtils.clearRoadWay(tuskBaseUrl, roadWayCode);
        if (hikRsVo != null && "0".equals(hikRsVo.getCode() )) {
            HikAgvRoadWay hikAgvRoadWay = new HikAgvRoadWay();
            hikAgvRoadWay.setRoadWayCode(roadWayCode);
            hikAgvRoadWay.setSeq("0");
            hikAgvRoadWay.setTrainSeq(0);
            hikAgvRoadWay.setTrainRoadWaySeq(0);
            hikAgvRoadWay.setPlateNumber("");
            hikAgvRoadWay.setClientId("");
            hikAgvRoadWay.setClientName("");
            hikAgvRoadWayMapper.updateById(hikAgvRoadWay);
        }
        return ResponseData.success();
    }

    @Override
    public ResponseData cancelTask(String taskCode) {
        HikRsVo hikRsVo = HikApiUtils.cancelTask(tuskBaseUrl, taskCode);
        if (hikRsVo == null) {
            return ResponseData.error("接口调用错误");
        } else if (!"0".equals(hikRsVo.getCode() )) {
            return ResponseData.error(hikRsVo.getMessage());
        }

        return ResponseData.success();
    }


    @Override
    public void agvCallback(HiKAgvCallbackParm hiKAgvCallbackParm) {
        //时间格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取taskCode，
        String taskCode = hiKAgvCallbackParm.getTaskCode();
        // 获取 操纵方法
        String method = hiKAgvCallbackParm.getMethod();
        // 获取AGV小车
        String robotCode = hiKAgvCallbackParm.getRobotCode();
        // 巷道编号
        String roadWayCode = hiKAgvCallbackParm.getRoadWayCode();
        // 巷道内顺序号
        String seq = hiKAgvCallbackParm.getSeq();

        // 当前位置编号
        String currentPositionCode = hiKAgvCallbackParm.getCurrentPositionCode();
        HikAgvTaskParam paramCondition = new HikAgvTaskParam();
        paramCondition.setTaskNo(taskCode);
        if ("outbin".equals(method)) {
            // 离开存储位，将任务状态修改为 10
            paramCondition.setAgvCode(robotCode);
            paramCondition.setStat("10");
            paramCondition.setGetCompleteTime(new Date());
            this.baseMapper.updateByTaskNo(paramCondition);
        } else if ("end".equals(method)) {
            // 任务结束，将任务状态修改为 20
            paramCondition.setStat("20");
            paramCondition.setPutCompleteTime(new Date());
            this.baseMapper.updateByTaskNo(paramCondition);
            if (StringUtils.isNotBlank(roadWayCode) && StringUtils.isNotBlank(seq)) {
                HikAgvRoadWay hikAgvRoadWay = new HikAgvRoadWay();
                hikAgvRoadWay.setRoadWayCode(roadWayCode);
                hikAgvRoadWay.setSeq(seq);
                hikAgvRoadWayMapper.updateById(hikAgvRoadWay);
            }
        } else if ("cancel".equals(method)) {
            // 任务取消，将任务状态修改为 90
            paramCondition.setStat("90");
            paramCondition.setCancelTime(new Date());
            this.baseMapper.updateByTaskNo(paramCondition);
        }

    }

    @Override
    public void agvStorageCallback(HiKAgvCallbackParm hiKAgvCallbackParm) {

        // 获取taskCode，
        String taskCode = hiKAgvCallbackParm.getTaskCode();
        // 获取 操纵方法
        String method = hiKAgvCallbackParm.getMethod();
        // 获取AGV小车
        String robotCode = hiKAgvCallbackParm.getRobotCode();
        if ("outbin".equals(method)) {
            // 离开存储位，将任务状态修改为 10
            //取货
            this.agvStorageTaskService.lambdaUpdate()
                    .eq(AgvStorageTask::getTaskNo,taskCode)
                    .set(AgvStorageTask::getAgvNo,robotCode)
                    .update();
            //获取拣货单号
            AgvStorageTask one = this.agvStorageTaskService.lambdaQuery().eq(AgvStorageTask::getTaskNo, taskCode).one();
            HxStorageOut hxStorageOut = this.hxStorageOutService.lambdaQuery().eq(HxStorageOut::getStorageNumber, one.getStorageNumber()).one();
            if(hxStorageOut != null){
                //修改拣选人
                this.hxStorageOutService.lambdaUpdate()
                        .eq(HxStorageOut::getId,hxStorageOut.getId())
                        .set(HxStorageOut::getAgvNo,robotCode)
                        .update();
            }
        }else if("end".equals(method)){
            this.agvStorageTaskService.lambdaUpdate()
                    .eq(AgvStorageTask::getTaskNo,taskCode)
                    .set(AgvStorageTask::getTaskStat,"00")
                    .update();
        }
    }

    private Serializable getKey(HikAgvTaskParam param){
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private HikAgvTask getOldEntity(HikAgvTaskParam param) {
        return this.getById(getKey(param));
    }

    private HikAgvTask getEntity(HikAgvTaskParam param) {
        HikAgvTask entity = new HikAgvTask();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

}
